package src;

import java.io.BufferedWriter;

import java.util.Map;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;

public class RessourceManager {
	
	private Map<Integer, String> puffer;
	private int myID;
	private SynchronizedCounter logSeqNr;
	private ArrayList<Integer> openTransactions;
	private int myTransaction = 0;
	protected static RessourceManager itsInstance;
	
	
	public RessourceManager (int ID){ 
		puffer = new ConcurrentHashMap<Integer, String>();
		logSeqNr = new SynchronizedCounter();
		openTransactions = new ArrayList<Integer>();
		pruefeLogFile();
		myID = ID;
		System.out.println("Ressourcenmanager "+ myID +" erzeugt");
	}
	
	public boolean prepare(int taid){
		// false = aborted, true = prepared
		boolean result = false;
		
		int logNr = 0;
		
		logNr = writeLogFile(taid, "prepare");
		result = tryPufferToFile();
		
		if (logNr > 0) result=true;
		
		return result;
	}
	
	public void commit(int taid){
		writeLogFile(taid, "commit");
		writeToFile();
	}
	
	public void rollback(int taid){
		writeLogFile(taid, "rollback");
		puffer.clear();				
	}
	
	private void pruefeLogFile(){
		// 
		try {
			FileReader fr = new FileReader("./Data/LogfileRM.txt");
			BufferedReader br = new BufferedReader(fr);
			while(true){
				String line =br.readLine();
				if(line != null){
					StringTokenizer Toke = new StringTokenizer(line, ";");
					if(line.indexOf("Commit")>-1){
						Toke.nextToken(); // Token Commit brauchen wir nicht im LogEntry
						LogEntry entry = new LogEntry(Integer.parseInt(Toke.nextToken()),Integer.parseInt(Toke.nextToken()),Toke.nextToken());
						System.out.println(entry);	
					}		
				}
				else{
					break;
				}
			}
			fr.close();
		}
		catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public boolean write(int taid, int pid, String data){
		if (myTransaction == 0){
			Koordinator.getInstance().reg(this, taid);
		}
		myTransaction = taid;
		//puffer.put(pid,String.valueOf(taid+";"+LogNr+";"+data));
		puffer.put(pid,String.valueOf(taid+";"+data));
		System.out.println("Transaktion " +taid + " schreibt " + data + " in Seite "+ pid );
		boolean result = false;
		return result;
	}
		//puffer.put(pid,String.valueOf(taid+";"+LogNr+";"+data));
		//System.out.println("Schreibe Seite "+pageid+" aus Transaktion "+taid+ " in den Puffer");
		//System.out.println(puffer);
		
//		//Liste der offenen transaktionen
//		Boolean bfound = false;
//		for (Integer item : openTransactions){
//			if (item == taid){
//				bfound = true;
//			}	
//		}
//		if (bfound == false){
//			openTransactions.add(taid);
//		}
	
	public boolean tryPufferToFile(){
		boolean result= true;
		try{
			Iterator<Integer> keySetItr = puffer.keySet().iterator();  
			  while( keySetItr.hasNext()) {
			   Integer key = keySetItr.next();
			   String value = puffer.get(key);
			   StringTokenizer st = new StringTokenizer(value, ";");
//			   String gesuchteTaid = st.nextToken();
//				if (Integer.parseInt(gesuchteTaid)==taid){
			   		st.nextToken(); // Taid
			   		st.nextToken();
					//int TempSeqNr = Integer.parseInt(st.nextToken());
					String dataobj = st.nextToken();
					tryWrite(key, dataobj );
					//writeCommitLog(taid, key, dataobj);
					//try{
						//keySetItr.remove();	
					}
				}
			catch (Exception e) {
				result = false;
					}
					
//				}
			 return result;
			 }
	
	private void writeToFile(){
			try
			{
				//s
				FileWriter fw = new FileWriter("./Data/Seiten.txt", true);
				//System.out.println(file.getAbsolutePath());
				BufferedWriter out = new BufferedWriter(fw);
				
				Iterator<Integer> keySetItr = puffer.keySet().iterator();  
				  while( keySetItr.hasNext()) {
					  Integer key = keySetItr.next();
					  out.write(puffer.get(key));
					  out.newLine();
					  System.out.println("Permanent geschrieben "+puffer.get(key));
					  puffer.remove(key);
				  }
				
				
				//fw.write(taid+";"+pageid+";"+ data);
				//System.out.println("Schreibe Seite "+pageid+" aus Transaktion "+taid+" persistent");
				out.close();
				fw.close();
			}
			catch( IOException e )
			{
				e.printStackTrace();
			}
		}
	
		public void readLogFile(){
			try {
				FileReader fr = new FileReader("./Data/LogfileRM.txt");
				BufferedReader br = new BufferedReader(fr);
				String s;
				while(true){
					String line =br.readLine();
					if(line != null){
						if(line.indexOf("Commit")>-1){
							System.out.println(line);	
						}		
					}
					else{
						break;
					}
				}
				fr.close();
			}
			catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		public void tryWrite(int taid, String data){
			try
			{			
				FileWriter fw = new FileWriter("./Data/Probe.txt",true);
				BufferedWriter out = new BufferedWriter(fw);
				
				out.write (data+";"+ taid +";");
				// z.B: prepare;1;12
				out.newLine();
				out.close();
				fw.close();
				
			}
			catch( IOException e )
			{
				e.printStackTrace();
			}
			
		}
		public int writeLogFile(int taid, String modus){
			int TempLogSeqNr;
			TempLogSeqNr =  logSeqNr.incrementAndGet();
			try
			{			
				FileWriter fw = new FileWriter("./Data/LogfileRM.txt",true);
				BufferedWriter out = new BufferedWriter(fw);
				
				out.write (modus+";"+ taid +";"+ TempLogSeqNr);
				// z.B: prepare;1;12
				out.newLine();
				out.close();
				fw.close();
				
			}
			catch( IOException e )
			{
				e.printStackTrace();
			}
			return TempLogSeqNr;
		}
		
		public String toString(){
			String result = "RessourcenManagerID: " + myID;  
			return result;
		}
		
//		public int writeCommitLog(int taid, int pageid, String data){
//			int TempLogSeqNr;
//			TempLogSeqNr =  logSeqNr.incrementAndGet();
//			try
//			{			
//				FileWriter fw = new FileWriter("./Data/Logfile.txt",true);
//				BufferedWriter out = new BufferedWriter(fw);
//				out.write("Commit "+TempLogSeqNr+";"+taid+";"+pageid+";"+ data);
//				out.newLine();
//				out.close();
//				fw.close();
//				
//			}
//			catch( IOException e )
//			{
//				e.printStackTrace();
//			}
//			return TempLogSeqNr;
//		}
}
